package com.karry.commons.web.storage;

import com.google.common.collect.ImmutableMap;
import com.karry.commons.util.DownloadView;
import com.karry.commons.vo.JsonResponse;
import org.ponly.fs.FileSystem;
import org.ponly.fs.util.StorageUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;



/**
 *   文件上传下载公共接口
 */
@Controller
@RequestMapping("/storage")
public class StorageController implements ServletContextAware {
    private static final Logger LOG = LoggerFactory.getLogger(StorageController.class);
    public static final String DEFAULT_FILE_MIME_TYPE = "application/octet-stream";
    public static final String DEFAULT_IMAGE_MIME_TYPE = "image/jpeg";
    private ServletContext servletContext;
    @Autowired
    private FileSystem fileSystem;


    /**********************************************
     *                 文件操作-Begin               *
     * *******************************************/

    /**
     *  通用上传文件
     * @param multipart
     * @return
     * @throws IOException
     */
    @ResponseBody
    @RequestMapping(value = "files/ul", method = RequestMethod.POST)
    public JsonResponse upload(@RequestPart("file") MultipartFile multipart) throws IOException {
        JsonResponse message;
        if (multipart == null || multipart.isEmpty()) {
            message = JsonResponse.fail("无效的文件, 文件不能为空");

        }else {
            String name = multipart.getOriginalFilename();
            InputStream inputStream = multipart.getInputStream();
            String path = StorageUtil.store(fileSystem,name, true, inputStream,true);
            message = JsonResponse.success(ImmutableMap.<String, Object>of("path", path,"fileName",name));
        }
        return message;
    }

    /**
     *  头像上传
     * @param multipart
     * @return
     * @throws IOException
     */
    @ResponseBody
    @RequestMapping(value = "/avatar/ul", method = RequestMethod.POST)
    public Map<String,Object> avatarUpload(@RequestPart("file") MultipartFile multipart) throws IOException {
        Map<String,Object> rsMap = new HashMap<>();
        if (multipart == null || multipart.isEmpty()) {
            rsMap.put("success",false);
            rsMap.put("msg","无效的文件");
        }
        String name = multipart.getOriginalFilename();
        InputStream inputStream = multipart.getInputStream();
        String path = StorageUtil.store(fileSystem,name, true, inputStream,true);
        rsMap.put("success",true);
        rsMap.put("msg","头像保存成功");
        rsMap.put("avatarUrl",path);
        return rsMap;
    }

    /**
     * 内联方式获取文件资源
     * @param fid
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping("files/{fid:.*}") // spring 默认会去掉后缀, 使用 .* 避免
    public void inline(@PathVariable("fid") String fid, HttpServletRequest request, HttpServletResponse response) throws IOException {
        final InputStream is = StorageUtil.readAsStream(fid,false,fileSystem);
        if (null != is) {
            String mimeType = getMimeType(fid);
            if (StringUtils.hasText(mimeType)) {
                response.setContentType(mimeType);
            }

            new DownloadView("", false) {
                @Override
                protected InputStream getResourceAsStream() {
                    return is;
                }
            }.sendTo(request, response);

        } else {
            // writer.write("您下载的文件不存在")
            response.sendError(HttpServletResponse.SC_NOT_FOUND, "File Not Find");
        }
    }

    /**
     * 文件下载
     * @param fid
     * @param filename
     * @param responseContentType
     * @param request
     * @param response
     * @throws IOException
     */
    @RequestMapping("files/dl/{fid:.*}")
    // @RequestMapping("dl/{hash}/{filename}")
    public void download(@PathVariable("fid") String fid, String filename, String responseContentType, HttpServletRequest request, HttpServletResponse response) throws IOException {
        final InputStream is = StorageUtil.readAsStream(fid, false,fileSystem);
        if (null != is) {
            filename = StringUtils.hasText(filename) ? filename : fid;
            // response.setHeader("Content-MD5", hash);

            // 如果 contentType 为空, 尝试从 filename 中获取
            if (!StringUtils.hasText(responseContentType)) {
                responseContentType = getMimeType(filename);
            }

            // 如果 contentType 仍然为空, 尝试从标识中获取
            if (!StringUtils.hasText(responseContentType)) {
                responseContentType = getMimeType(fid);
            }

            responseContentType = StringUtils.hasText(responseContentType) ? responseContentType : DEFAULT_FILE_MIME_TYPE;

            new DownloadView(filename, responseContentType) {
                @Override
                protected InputStream getResourceAsStream() {
                    return is;
                }
            }.sendTo(request, response);
        } else {
            response.sendError(HttpServletResponse.SC_NOT_FOUND, "File Not Find");
        }
    }


    /**
     * 裁剪图片   /images/aa.jpg_120x120
     */
    @RequestMapping("images/{path:.*}")
    public void view(@PathVariable("path") String path, boolean download, HttpServletResponse response) throws IOException {
        final InputStream is = StorageUtil.readAsStream(path,true,fileSystem);
        if (null != is) {
            String type = getMimeType(path);
            type = StringUtils.hasText(type) ? type : DEFAULT_IMAGE_MIME_TYPE;

            new DownloadView("", type, download) {
                @Override
                protected InputStream getResourceAsStream() {
                    return is;
                }
            }.sendTo(null, response);
        }
    }

    /**********************************************
     *                 操作-END               *
     * *******************************************/






    private String getMimeType(String filename) {
        return servletContext.getMimeType(filename);
    }

    @Override
    public void setServletContext(ServletContext servletContext) {
        this.servletContext = servletContext;
    }



}
